From b9d11c5788280ab4530648d8cfcf8b4bbc32ea20 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 15:05:17 +0100 Subject: [PATCH] HVM patch to add pio IOREQ_WRITE OVERLAP/REPZ support in hvm io.c hvm_pio_assist(). Also, cleaned up a bit of duplicate code in the functions. Simple guest tests (ide pio) pass now for overlapped/rep write operations. Signed-off-by: Tom Woller Signed-off-by: Mats Petersson --- xen/arch/x86/hvm/io.c | 55 ++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 893dd68ce5..fd9ff611df 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -365,29 +365,42 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p, unsigned long old_eax; int sign = p->df ? -1 : 1; - if (p->dir == IOREQ_WRITE) { - if (p->pdata_valid) { - regs->esi += sign * p->count * p->size; - if (mmio_opp->flags & REPZ) - regs->ecx -= p->count; - } - } else { - if (mmio_opp->flags & OVERLAP) { - unsigned long addr; - + if (p->pdata_valid || (mmio_opp->flags & OVERLAP)) { + if (mmio_opp->flags & REPZ) + regs->ecx -= p->count; + if (p->dir == IOREQ_READ) { regs->edi += sign * p->count * p->size; - if (mmio_opp->flags & REPZ) - regs->ecx -= p->count; - addr = regs->edi; - if (sign > 0) - addr -= p->size; - hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); - } else if (p->pdata_valid) { - regs->edi += sign * p->count * p->size; - if (mmio_opp->flags & REPZ) - regs->ecx -= p->count; - } else { + if (mmio_opp->flags & OVERLAP) { + /* + * If we are doing in IN and it's overlapping a page boundary, + * we need to copy the data back to user's page with hvm_copy. + * Note that overlap * can only be set with paging enabled, so + * we don't need to worry about * real-mode stuff. + */ + unsigned long addr; + { + /* + * We completely ignore segment registers here - + * it's not a good idea. We also may use upper bits + * in edi when in 16-bit real/protected mode. + * We really need to get the actual address back from + * the arch-dependant HVM portion. + */ + struct vcpu *v = current; + if (hvm_realmode(v)) + __hvm_bug(regs); + } + addr = regs->edi; + if (sign > 0) + addr -= p->size; + hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); + } + } else + regs->esi += sign * p->count * p->size; + + } else { + if (p->dir == IOREQ_READ) { old_eax = regs->eax; switch (p->size) { case 1: -- 2.30.2